<template>
  <div class="RecentProfitPanel">
    <div class="RecentProfitPanel-header">
      <div class="RecentProfitPanel-header-title">近期利润</div>
      <el-radio-group v-model="rangeDays" size="small" @change="handleRangeChange">
        <el-radio-button :label="7">近7天</el-radio-button>
        <el-radio-button :label="14">近14天</el-radio-button>
        <el-radio-button :label="30">近30天</el-radio-button>
      </el-radio-group>
      <el-button size="small" text @click="reload" :loading="loading">刷新</el-button>
    </div>
    <div class="RecentProfitPanel-chart" ref="chartRef">
      <div v-if="!loading && !chartData.length" class="RecentProfitPanel-empty">暂无数据</div>
    </div>
  </div>
</template>

<script setup>
import {ref, onMounted, watch, nextTick, onBeforeUnmount} from 'vue'
import * as echarts from 'echarts'
import {ElMessage} from 'element-plus'
import {listProfits} from '../../../api/profitApi.js'

// 选择的区间天数
const rangeDays = ref(7)
// 图表 DOM 引用
const chartRef = ref(null)
let chartInstance = null
// 原始图表数据（[{date:'YYYY-MM-DD', profit: number}])
const chartData = ref([])
// 加载状态
const loading = ref(false)

const formatDate = (d) => {
  const y = d.getFullYear()
  const m = `${d.getMonth() + 1}`.padStart(2, '0')
  const day = `${d.getDate()}`.padStart(2, '0')
  return `${y}-${m}-${day}`
}

const buildContinuousDates = (startDateStr, endDateStr, map) => {
  const res = []
  const start = new Date(startDateStr)
  const end = new Date(endDateStr)
  for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
    const label = formatDate(d)
    res.push({date: label, profit: map.get(label) ?? 0})
  }
  return res
}

const loadData = async () => {
  loading.value = true
  try {
    const end = new Date()
    const start = new Date()
    start.setDate(end.getDate() - (rangeDays.value - 1))
    const startDate = formatDate(start)
    const endDate = formatDate(end)
    const payload = {mode: 'day', startDate, endDate}
    const res = await listProfits(payload)
    // 后端返回对象包含 list: [{label:'YYYY-MM-DD', profit: BigDecimal}]
    const list = (res && Array.isArray(res.list)) ? res.list : []
    const map = new Map(list.map(i => [i.label, Number(i.profit) || 0]))
    chartData.value = buildContinuousDates(startDate, endDate, map)
  } catch (e) {
    ElMessage.error('获取利润数据失败')
    chartData.value = []
  } finally {
    loading.value = false
    await nextTick()
    renderChart()
  }
}

const handleRangeChange = () => {
  loadData()
}

const reload = () => loadData()

const renderChart = () => {
  if (!chartRef.value) return
  if (!chartInstance) {
    chartInstance = echarts.init(chartRef.value)
    window.addEventListener('resize', handleResize)
  }
  const xData = chartData.value.map(i => i.date.slice(5)) // 取 MM-DD
  const yData = chartData.value.map(i => i.profit)
  const positive = yData.some(v => v > 0)
  const negative = yData.some(v => v < 0)
  const yMin = negative ? Math.min(...yData, 0) : 0
  const yMax = positive ? Math.max(...yData, 0) : 0
  const option = {
    tooltip: {trigger: 'axis', valueFormatter: (v) => v == null ? '-' : (Number(v).toFixed(2) + ' 元')},
    grid: {top: 8, right: 8, left: 56, bottom: 32},
    xAxis: {
      type: 'category',
      data: xData,
      boundaryGap: false,
      axisTick: {show: false}
    },
    yAxis: {
      type: 'value',
      axisLine: {show: false},
      axisTick: {show: false},
      splitLine: {lineStyle: {color: '#f0f2f5'}},
      min: yMin,
      max: yMax,
      axisLabel: {formatter: (v) => Number(v).toFixed(0) + ' 元'}
    },
    series: [
      {
        name: '利润(元)',
        type: 'line',
        data: yData,
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        showSymbol: yData.length <= 31,
        lineStyle: {color: '#409EFF', width: 2},
        itemStyle: {color: '#409EFF'},
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            {offset: 0, color: 'rgba(64,158,255,0.35)'},
            {offset: 1, color: 'rgba(64,158,255,0.05)'}
          ])
        },
        markLine: (negative && positive) ? {data: [{yAxis: 0}], lineStyle: {color: '#909399'}} : undefined
      }
    ]
  }
  chartInstance.setOption(option)
}

const handleResize = () => {
  if (chartInstance) chartInstance.resize()
}

watch(chartData, () => {
  // 数据改变后已在 loadData 里调用 renderChart，这里可保底
  renderChart()
})

onMounted(() => {
  loadData()
})

onBeforeUnmount(() => {
  if (chartInstance) {
    chartInstance.dispose()
    chartInstance = null
  }
  window.removeEventListener('resize', handleResize)
})
</script>

<style scoped lang="scss">
.RecentProfitPanel {
  display: flex;
  flex-direction: column;
  padding: 16px;
  background: linear-gradient(180deg, #ffffff 0%, #fafbfc 100%);
  border: 1px solid #e8ebf0;
  border-radius: 12px;
  height: 100%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.04);
  transition: box-shadow .2s ease;
  overflow: hidden;

  &:hover {
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08), 0 8px 20px rgba(0, 0, 0, 0.06);
  }

  &-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;

    &-title {
      font-size: 18px; /* 明确字号 */
      font-weight: 600;
      color: #303133; /* 明确颜色 */
      line-height: 1.2;
      margin-right: auto; /* 推动后续控件到右侧 */
      display: flex;
      align-items: center;
      white-space: nowrap;
      flex: 0 0 auto; /* 禁止被压缩为0 */
      min-width: 80px; /* 保证最小可视宽度 */
    }
  }

  &-chart {
    flex: 1;
    width: 100%;
    position: relative;
    min-height: 180px;
  }

  &-empty {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 14px;
    color: #909399;
    user-select: none;
  }
}
</style>
